package com.authentication.filter;

import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.NestedServletException;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 捕获 访问 oauth2 resource server 因权限不足产生的    {@link HttpClientErrorException}
 * 并把用户重定向到登陆界面
 */
public class Oauth2ExceptionTranslatorFilter extends OncePerRequestFilter {

    private final AuthenticationEntryPoint authenticationEntryPoint;

    private final RequestCache requestCache;

    public Oauth2ExceptionTranslatorFilter(AuthenticationEntryPoint authenticationEntryPoint, RequestCache requestCache) {
        this.requestCache = requestCache;
        this.authenticationEntryPoint = authenticationEntryPoint;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (NestedServletException e) {


            Throwable rootCause = e.getRootCause();

            if (rootCause instanceof HttpClientErrorException) {
                HttpClientErrorException authenticationException = (HttpClientErrorException) rootCause;
                requestCache.saveRequest(request, response);
                authenticationEntryPoint.commence(request, response, new InsufficientAuthenticationException(authenticationException.getMessage()) );
            } else {
                throw e;
            }

        }
    }
}
